package com.jsmile.cloud.goodscenter.spu.model;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.jsmile.cloud.goodscenter.api.constants.GoodsConstants;
import com.jsmile.cloud.goodscenter.api.enums.*;
import com.jsmile.cloud.goodscenter.api.req.spu.*;
import com.jsmile.cloud.goodscenter.spu.event.*;
import com.jsmile.mail.security.event.DomainEventPublisher;
import com.jsmile.mall.api.exception.ExceptionKit;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author 龚亮
 * @version 1.0
 * @desc 为了薪资破万，还是睡一会儿吧...!
 * @date 2020年06月04日 03:56:49
 */
@ApiModel
@Data
@TableName("t_spu")
public class Spu extends Model<Spu> {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "id")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    @ApiModelProperty(value = "商品id")
    private Long spuId;
    @ApiModelProperty(value = "第三方商品id")
    private String thirdSpuId;
    @ApiModelProperty(value = "商品是否显示 1：是 0：否")
    private Integer hasShow;
    @ApiModelProperty(value = "创建时间")
    private Date createTime;
    @ApiModelProperty(value = "创建人")
    private String createBy;
    @ApiModelProperty(value = "更新时间")
    private Date updateTime;
    @ApiModelProperty(value = "更新人")
    private String updateBy;
    @ApiModelProperty(value = "删除标记位 0:有效 1:删除")
    @TableLogic
    private Integer delFlag;
    @ApiModelProperty(value = "租户id")
    private Long tenantId;
    @ApiModelProperty(value = "供应商id")
    private Long supplyId;
    @ApiModelProperty(value = "供应商名称")
    private String supplyName;
    @ApiModelProperty(value = "商品名称")
    private String spuName;
    @ApiModelProperty(value = "详情描述")
    private String spuDetail;
    @ApiModelProperty(value = "备注")
    private String remark;
    @ApiModelProperty(value = "后端类目id")
    private Long categoryId;
    @ApiModelProperty(value = "品牌id")
    private Long brandId;
    @ApiModelProperty(value = "商品编号")
    private String spuNo;
    @ApiModelProperty(value = "缩略图")
    private String imageUrl;
    @ApiModelProperty(value = "副标题")
    private String subHead;
    @ApiModelProperty(value = "最低起买: 单位为lot_size")
    private Integer minBuyNum;
    @ApiModelProperty(value = "是否分享，0：不分享，1分享")
    private Integer shareFlag;
    @ApiModelProperty(value = "配送方式,1:自提,2:快递配送")
    private Integer deliveryType;
    @ApiModelProperty(value = "运费模板id")
    private Long templateId;
    @ApiModelProperty(value = "商品类型 1:供应商商品 2:店铺商品")
    private Integer spuType;
    @ApiModelProperty(value = "上架状态 1上架 2下架")
    private Integer saleStatus;
    @ApiModelProperty(value = "商品销量")
    private Integer goodsSales;
    @ApiModelProperty(value = "商品库存")
    private Integer goodsStock;
    @ApiModelProperty(value = "审核状态 1：未提交，2:待审核，3:未通过，4:通过")
    private Integer reviewStatus;
    @ApiModelProperty(value = "审核不通过原因")
    private String reviewErrMsg;
    @ApiModelProperty(value = "1:启售，2:停售")
    private Integer saleFlag;
    @ApiModelProperty(value = "平台id")
    private Integer platformId;
    @ApiModelProperty(value = "业务id")
    private Integer bizCode;
    @ApiModelProperty(value = "发布状态 1:发布，2:未发布")
    private Integer publishStatus;
    @ApiModelProperty(value = "最低销售价")
    private Long lowSellingPrice;
    @ApiModelProperty(value = "最高销售价")
    private Long highSellingPrice;
    @ApiModelProperty(value = "最低市场价")
    private Long lowMarketPrice;
    @ApiModelProperty(value = "最高市场价")
    private Long highMarketPrice;
    @ApiModelProperty(value = "最低券后价")
    private Long lowCouponPrice;
    @ApiModelProperty(value = "最高券后价")
    private Long highCouponPrice;
    @ApiModelProperty(value = "最低平台价")
    private Long lowPlatformPrice;
    @ApiModelProperty(value = "最高平台价")
    private Long highPlatformPrice;
    @TableField(exist = false)
    @ApiModelProperty(value = "sku信息")
    private List<SkuInfo> skuList;
    @TableField(exist = false)
    @ApiModelProperty(value = "删除的sku信息")
    private List<SkuInfo> deleteSkuList;
    @TableField(exist = false)
    @ApiModelProperty(value = "商品主图")
    private List<SpuImage> imageUrls;
    @TableField(exist = false)
    @ApiModelProperty(value = "商品详情图")
    private List<SpuImage> imageDetailUrls;

    // 商品新增
    public static Spu create(ReqSpuAdd reqSpuAdd) {
        Spu spu = BeanUtil.toBean(reqSpuAdd, Spu.class);
        spu.setCreateTime(new Date());
        spu.setTenantId(reqSpuAdd.getCurTenantId());
        spu.setSaleFlag(SaleFlagEnum.OPEN.getValue());
        spu.setReviewStatus(GoodsReviewStatusEnum.PASS.getValue());
        spu.setImageUrl(reqSpuAdd.getImageUrl().get(0));
        spu.setSpuId(IdUtil.getSnowflake(GoodsConstants.SNOWFLAKE.workerId, GoodsConstants.SNOWFLAKE.datacenterId).nextId());
        spu.setImageUrls(SpuImage.createHeadImage(reqSpuAdd.getImageUrl(), reqSpuAdd.getCurTenantId(), spu.getSpuId()));
        spu.setImageDetailUrls(SpuImage.createDetailImage(reqSpuAdd.getImageDetailUrl(), reqSpuAdd.getCurTenantId(), spu.getSpuId()));
        spu.setSkuList(SkuInfo.create(reqSpuAdd.getSkuList(), reqSpuAdd.getCurTenantId(), spu.getSpuId()));
        DomainEventPublisher.publish(new SpuCreateEvent(spu));
        spu.setLowMarketPrice(spu.getSkuList().stream().map(SkuInfo::getMarketPrice).min(Long::compareTo).orElse(0L));
        spu.setHighMarketPrice(spu.getSkuList().stream().map(SkuInfo::getMarketPrice).max(Long::compareTo).orElse(0L));
        spu.setGoodsStock(spu.getSkuList().stream().mapToInt(SkuInfo::getInventory).sum());
        return spu;
    }

    // 商品编辑
    public static Spu edit(ReqSpuEdit reqSpuEdit) {
        Spu spu = BeanUtil.toBean(reqSpuEdit, Spu.class);
        spu.setReviewStatus(GoodsReviewStatusEnum.CHECK.getValue());
        spu.setPublishStatus(PublishStatusEnum.NOT_PUBLISH.getValue());
        spu.setImageUrl(reqSpuEdit.getImageUrl().get(0));
        spu.setTenantId(reqSpuEdit.getCurTenantId());
        spu.setUpdateTime(new Date());
        spu.setSpuId(reqSpuEdit.getSpuId());
        spu.setImageUrls(SpuImage.createHeadImage(reqSpuEdit.getImageUrl(), reqSpuEdit.getCurTenantId(), spu.getSpuId()));
        spu.setImageDetailUrls(SpuImage.createDetailImage(reqSpuEdit.getImageDetailUrl(), reqSpuEdit.getCurTenantId(), spu.getSpuId()));
        spu.setSkuList(SkuInfo.edit(reqSpuEdit.getSkuList(), reqSpuEdit.getCurTenantId(), spu.getSpuId()));
        spu.setDeleteSkuList(SkuInfo.delete(reqSpuEdit.getDeleteSkuList(), reqSpuEdit.getCurTenantId(), spu.getSpuId()));
        spu.setLowMarketPrice(spu.getSkuList().stream().map(SkuInfo::getMarketPrice).min(Long::compareTo).orElse(0L));
        spu.setHighMarketPrice(spu.getSkuList().stream().map(SkuInfo::getMarketPrice).max(Long::compareTo).orElse(0L));
        DomainEventPublisher.publish(new SpuEditEvent(spu));
        return spu;
    }

    // 商品上架
    public void putSpuByMerchant(ReqSpuSaleStatus reqSpuSaleStatus) {
        ExceptionKit.checkArgument(PublishStatusEnum.PUBLISH.getValue() != this.getPublishStatus(), "未发布的商品不能上架!");
        ExceptionKit.checkArgument(SaleFlagEnum.OPEN.getValue() != this.getSaleFlag(), "停售的商品不能上架!");
        this.setSaleStatus(SaleStatusEnum.PUT.getValue());
        this.setUpdateTime(new Date());
        Map<Long, ReqSpuSaleStatus.SkuSaleStatus> skuMap = reqSpuSaleStatus.getSkuList().stream().collect(Collectors.toMap(ReqSpuSaleStatus.SkuSaleStatus::getSkuId, a -> a));
        this.getSkuList().forEach(x -> {
            ExceptionKit.checkArgument(skuMap.get(x.getSkuId()).getCouponPrice() < x.getPlatformPrice(), "券后价必须大于等于平台价!");
            ExceptionKit.checkArgument(skuMap.get(x.getSkuId()).getSellingPrice() < skuMap.get(x.getSkuId()).getCouponPrice(), "销售价必须大于等于券后价!");
            x.setCouponPrice(skuMap.get(x.getSkuId()).getCouponPrice());
            x.setSellingPrice(skuMap.get(x.getSkuId()).getSellingPrice());
            x.setUpdateTime(new Date());
        });
        this.setLowCouponPrice(this.getSkuList().stream().map(SkuInfo::getCouponPrice).min(Long::compareTo).orElse(0L));
        this.setHighCouponPrice(this.getSkuList().stream().map(SkuInfo::getCouponPrice).max(Long::compareTo).orElse(0L));
        this.setLowSellingPrice(this.getSkuList().stream().map(SkuInfo::getSellingPrice).min(Long::compareTo).orElse(0L));
        this.setHighSellingPrice(this.getSkuList().stream().map(SkuInfo::getSellingPrice).max(Long::compareTo).orElse(0L));
        DomainEventPublisher.publish(new SpuPutEvent(this));
    }

    // 商品下架
    public void pullSpuByMerchant() {
        this.setSaleStatus(SaleStatusEnum.PULL.getValue());
        this.setUpdateTime(new Date());
        DomainEventPublisher.publish(new SpuPullEvent(this));
    }

    // 商品审核通过
    public void reviewSpu(ReqSpuReview reqSpuReview) {
        this.setReviewStatus(GoodsReviewStatusEnum.PASS.getValue());
        this.setPublishStatus(PublishStatusEnum.PUBLISH.getValue());
        this.setUpdateTime(new Date());
        this.setSpuDetail(reqSpuReview.getSpuDetail());
        Map<Long, ReqSpuReview.SkuReview> skuMap = reqSpuReview.getSkuList().stream().collect(Collectors.toMap(ReqSpuReview.SkuReview::getSkuId, a -> a));
        this.getSkuList().forEach(x -> {
            ExceptionKit.checkArgument(skuMap.get(x.getSkuId()).getPlatformPrice() < x.getCostPrice(), "平台价必须大于等于供货价!");
            x.setUpdateTime(new Date());
            x.setPlatformPrice(skuMap.get(x.getSkuId()).getPlatformPrice());
        });
        this.setLowPlatformPrice(this.getSkuList().stream().map(SkuInfo::getPlatformPrice).min(Long::compareTo).orElse(0L));
        this.setHighPlatformPrice(this.getSkuList().stream().map(SkuInfo::getPlatformPrice).max(Long::compareTo).orElse(0L));
        DomainEventPublisher.publish(new SpuPublishEvent(this));
    }

    // 商品审核不通过
    public void reviewSpuNot(ReqSpuReviewNot reqSpuReviewNot) {
        this.setReviewStatus(GoodsReviewStatusEnum.NOT_PASS.getValue());
        this.setPublishStatus(PublishStatusEnum.NOT_PUBLISH.getValue());
        this.setUpdateTime(new Date());
        this.setReviewErrMsg(reqSpuReviewNot.getReviewErrMsg());
        // DomainEventPublisher.publish(new SpuPullEvent(this));
    }

    public void checkStatus() {
        ExceptionKit.checkArgument(SaleFlagEnum.OPEN.getValue() != this.getSaleFlag(), GoodsCodeEnum.GOODS_DOWN.getResCode(), GoodsCodeEnum.GOODS_DOWN.getResMsg());
        ExceptionKit.checkArgument(SaleStatusEnum.PUT.getValue() != this.getSaleStatus(), GoodsCodeEnum.GOODS_DOWN.getResCode(), GoodsCodeEnum.GOODS_DOWN.getResMsg());
        ExceptionKit.checkArgument(PublishStatusEnum.PUBLISH.getValue() != this.getPublishStatus(), GoodsCodeEnum.GOODS_DOWN.getResCode(), GoodsCodeEnum.GOODS_DOWN.getResMsg());

    }

}
